import { request } from 'http'
import { parseHeaders } from './helpers/headers'
import { AxiosPromise, AxiosRequestConfig, AxiosResponse } from './types'

export default function xhr(config: AxiosRequestConfig): AxiosPromise {
    return new Promise((resolve, reject) => {
        const { data = null, url, method = 'get', headers, responseType, timeout } = config

        const request = new XMLHttpRequest()

        if (responseType) {
            request.responseType = responseType
        }

        request.open(method.toUpperCase(), url, true)

        // 设置超时时间
        if (timeout) {
            request.timeout = timeout
        }

        request.onreadystatechange = function handleLoad() {
            if (request.readyState !== 4) {
                return
            }

            if (request.status === 0) {
                return
            }

            const reponseHeaders = parseHeaders(request.getAllResponseHeaders())

            // 拿到数据
            const responseData = responseType !== 'text' ? request.response : request.responseText

            const response: AxiosResponse = {
                data: responseData,
                status: request.status,
                statusText: request.statusText,
                headers: reponseHeaders,
                config,
                request
            }
            handleResponse(response)
        }

        request.onerror = function handleError() {
            reject(new Error('Network Error'))
        }

        request.ontimeout = function handleTimeout() {
            reject(new Error(`Timeout of ${timeout} ms exceeded`))
        }

        // 设置头
        Object.keys(headers).forEach(name => {
            // 如果data没有值，不设置头部 content-type
            if (data === null && name.toLocaleLowerCase() === 'content-type') {
                delete headers[name]
            } else {
                request.setRequestHeader(name, headers[name])
            }
        })

        request.send(data)

        // 处理异常状态码
        function handleResponse(response: AxiosResponse): void {
            if (response.status >= 200 && response.status < 300) {
                resolve(response)
            } else {
                reject(new Error(`Request failed with status code ${response.status}`))
            }
        }
    })
}
